package com.clp.protocol.core.utils;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

public class StringUtil {
    public static final char C_SLASH = '/';
    public static final char C_DOLLAR = '$';
    public static final char C_DOT = '.';
    public static final char C_COLON = ':';
    public static final char C_COMMA = ',';
    public static final char C_STRIKE = '-';
    public static final char C_LEFT_PARENTHESIS = '(';
    public static final char C_RIGHT_PARENTHESIS = ')';


    private StringUtil() {}

    /**
     * 将字节数组按照指定的字符集解码成成字符串
     *
     * @param bytes：要解码的字节数组
     * @param charsetName    ：utf-8、gbk、...
     * @return
     */
    public static String decode(byte[] bytes, String charsetName) {
        String retStr = "";
        try {
            retStr = new String(bytes, charsetName);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return retStr;
    }

    public static String decode(byte[] bytes, Charset charset) {
        return new String(bytes, charset);
    }

    /**
     * 将字符串按照指定的字符集编码成字节数组
     *
     * @param str：要编码的字符串
     * @param charsetName：utf-8、gbk、...
     * @return
     */
    public static byte[] encode(String str, String charsetName) {
        byte[] retBytes = null;
        try {
            retBytes = str.getBytes(charsetName);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return retBytes;
    }

    /**
     * 十六进制字符串转字节数组
     * @param strs：格式为["00", "01", "0A", ...]
     * @return
     */
    public static byte[] hexStrArrToByteArr(String[] strs) {
        if (strs.length == 0) return new byte[0];
        byte[] bytes = new byte[strs.length];
        int index = 0;
        for (String str : strs) {
            if (str == null || str.equals("")) continue;
            char[] chars = str.toCharArray();
            if (chars.length == 0) continue;
            try {
                int num = charToint(chars[0]);
                for (int i = 1; i < chars.length; i++) {
                    num = num * 16 + charToint(chars[i]);
                }
                bytes[index] = (byte) num;
                index += 1;
            } catch (ParseHexCharToIntException e) {
                e.printStackTrace();
            }
        }
        return bytes;
    }

    /**
     * 将字符转为int数字
     * @param aChar
     * @return
     * @throws ParseHexCharToIntException
     */
    public static int charToint(char aChar) throws ParseHexCharToIntException {
        switch (aChar) {
            case '0':
                return 0;
            case '1':
                return 1;
            case '2':
                return 2;
            case '3':
                return 3;
            case '4':
                return 4;
            case '5':
                return 5;
            case '6':
                return 6;
            case '7':
                return 7;
            case '8':
                return 8;
            case '9':
                return 9;
            case 'a':
                return 10;
            case 'A':
                return 10;
            case 'b':
                return 11;
            case 'B':
                return 11;
            case 'c':
                return 12;
            case 'C':
                return 12;
            case 'd':
                return 13;
            case 'D':
                return 13;
            case 'e':
                return 14;
            case 'E':
                return 14;
            case 'f':
                return 15;
            case 'F':
                return 15;
            default:
                throw new ParseHexCharToIntException("非法的字符：没有对应的数字与之对应！");
        }
    }

//    public static void main(String[] args) throws UnsupportedEncodingException {
//        String str = "中国";
//        //获取utf-8对应的的字符集
//        Charset charset = Charset.forName("utf-8");
//        //将字符串通过utf-8进行编码转化成字节
//        byte[] bytes = str.getBytes(charset);
//        //再将字节根据相同的编码格式进行解码
//        String string = new String(bytes, "utf-8");
//        System.out.println(string);
//    }

    /**
     * 解析字符01：#{}格式
     * @param str：
     * @param strObjs ：条件
     * @return
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    public static String parse01(String str, Map<String, Object> strObjs) {
        char[] chars = str.toCharArray();

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < chars.length;) {
            if (chars[i] != '#') {
                sb.append(chars[i]);
                i += 1;
                continue;
            }
            // chars[i] == '#'
            i += 1;

            int j = i;
            while (j < chars.length) {
                if (chars[j] == ' ') {
                    j += 1;
                    continue;
                }
                if (chars[j] != '{') throw new RuntimeException("非法字符");
                j += 1;

                int k = j;
                StringBuilder paramSb = new StringBuilder();
                while (k < chars.length) {
                    if (chars[k] == '}') {
                        k += 1;
                        break;
                    }
                    paramSb.append(chars[k]);
                    k += 1;
                }

                String paramStr = paramSb.toString();
                if (strObjs.containsKey(paramStr)) {
                    Object obj = strObjs.get(paramStr);
                    if (obj != null) {
                        sb.append(obj);
                    }
                } else {
                    sb.append("#{").append(paramSb).append("}");
                }

                i = k;
                break;
            }
        }
        return sb.toString();
    }

    /**
     * 提取字符串内的所有模式内容
     * @param str 要寻找的字符串
     * @param pattern 模式，如：${}, #() 这种
     * @return
     */
    public static List<String> extractPlaceholderContents(String str, String pattern) {
        char[] patternArray = pattern.toCharArray();
        if (patternArray.length != 3) {
            throw new IllegalArgumentException("非法模式：" + pattern + "，要求模式类似于 ${}、#() 这种");
        }

        char[] srcChars = str.toCharArray();
        char head = patternArray[0];
        char left = patternArray[1];
        char right = patternArray[2];

        List<String> retList = new ArrayList<>(16);
        StringBuilder sb;
        int index = 0;
        while (index < srcChars.length) {
            if (srcChars[index] != head) {
                index++;
                continue;
            }
            // srcChars[index] == '$'
            index++;
            if (index >= srcChars.length) throw new IllegalArgumentException("非法字符串：" + str);
            while (srcChars[index] == ' ') {
                index++;
                if (index >= srcChars.length) throw new IllegalArgumentException("非法字符串：" + str);
                continue;
            }
            if (srcChars[index] != left) throw new IllegalArgumentException("非法字符串：" + str);
            index++;
            if (index >= srcChars.length) throw new IllegalArgumentException("非法字符串：" + str);
            sb = new StringBuilder();
            while (srcChars[index] != right) {
                sb.append(srcChars[index]);
                index++;
                if (index >= srcChars.length) throw new IllegalArgumentException("非法字符串：" + str);
            }
            retList.add(sb.toString());
            index++;
        }

        return retList;
    }

    public static String replacePlaceholdersByOrder(String str, String pattern, List<?> list) {
        char[] patternArray = pattern.toCharArray();
        if (patternArray.length != 3) {
            throw new IllegalArgumentException("非法模式：" + pattern + "，要求模式类似于 ${}、#() 这种");
        }

        char[] srcChars = str.toCharArray();
        char head = patternArray[0];
        char left = patternArray[1];
        char right = patternArray[2];

        StringBuilder sb = new StringBuilder();
        int index = 0, listIndex = 0;
        while (index < srcChars.length) {
            if (srcChars[index] != head) {
                sb.append(srcChars[index]);
                index++;
                continue;
            }
            // srcChars[index] == '$'
            index++;
            if (index >= srcChars.length) throw new IllegalArgumentException("非法字符串：" + str);
            while (srcChars[index] == ' ') {
                index++;
                if (index >= srcChars.length) throw new IllegalArgumentException("非法字符串：" + str);
                continue;
            }
            if (srcChars[index] != left) throw new IllegalArgumentException("非法字符串：" + str);
            index++;
            if (index >= srcChars.length) throw new IllegalArgumentException("非法字符串：" + str);
            while (srcChars[index] != right) {
                index++;
                if (index >= srcChars.length) throw new IllegalArgumentException("非法字符串：" + str);
            }
            sb.append(list.get(listIndex));
            index++; listIndex++;
        }

        return sb.toString();
    }

    /**
     *
     * @param str dsafsad${ds}fd
     * @param pattern ${}
     * @param function 替换的函数
     * @return
     */
    public static String calcPlaceholders(String str, String pattern, Function<String, String> function) {
        if (str == null || pattern == null || function == null) return str;

        char[] patternArray = pattern.toCharArray();
        if (patternArray.length != 3) {
            throw new IllegalArgumentException("非法模式：" + pattern + "，要求模式类似于 ${}、#() 这种");
        }

        char[] srcChars = str.toCharArray();
        char head = patternArray[0];
        char left = patternArray[1];
        char right = patternArray[2];

        StringBuilder sb = new StringBuilder(str.length());
        int index = 0;
        while (index < srcChars.length) {
            if (srcChars[index] != head) {
                sb.append(srcChars[index]);
                index++;
                continue;
            }
            // srcChars[index] == '$'
            index++;
            if (index >= srcChars.length) throw new IllegalArgumentException("非法字符串：" + str);
            while (srcChars[index] == ' ') {
                index++;
                if (index >= srcChars.length) throw new IllegalArgumentException("非法字符串：" + str);
                continue;
            }
            if (srcChars[index] != left) throw new IllegalArgumentException("非法字符串：" + str);
            index++;
            if (index >= srcChars.length) throw new IllegalArgumentException("非法字符串：" + str);
            StringBuilder inSb = new StringBuilder();
            while (srcChars[index] != right) {
                inSb.append(srcChars[index]);
                index++;
                if (index >= srcChars.length) throw new IllegalArgumentException("非法字符串：" + str);
            }
            sb.append(function.apply(inSb.toString()));
            index++;
        }

        return sb.toString();
    }

    public static boolean isBlank(CharSequence cs) {
        int strLen = length(cs);
        if (strLen == 0) {
            return true;
        } else {
            for(int i = 0; i < strLen; ++i) {
                if (!Character.isWhitespace(cs.charAt(i))) {
                    return false;
                }
            }

            return true;
        }
    }

    public static int length(CharSequence cs) {
        return cs == null ? 0 : cs.length();
    }

    public static String formatNumberStr(int num, int width) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < width - (num + "").toCharArray().length; i++) {
            sb.append("0");
        }
        sb.append(num);
        return sb.toString();
    }
}
